package com.goldman.aplt.util;

import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 编辑距离计算类
 */
public class LevenshteinDistanceUtils {

    public static int lowerOfThree(int first, int second, int third)
    {
        int min = first;
        if (second < min)
            min = second;
        if (third < min)
            min = third;
        return min;
    }

    public static int compareDistance(String str1, String str2)
    {
        int[][] Matrix;
        int n = str1.length();
        int m = str2.length();

        int temp = 0;
        char ch1;
        char ch2;
        int i = 0;
        int j = 0;
        if (n == 0)
        {
            return m;
        }
        if (m == 0)
        {

            return n;
        }
        Matrix = new int[n + 1][m + 1];

        for (i = 0; i <= n; i++)
        {
            Matrix[i][0] = i;
        }

        for (j = 0; j <= m; j++)
        {
            Matrix[0][j] = j;
        }

        for (i = 1; i <= n; i++)
        {
            ch1 = str1.charAt(i - 1);
            for (j = 1; j <= m; j++)
            {
                ch2 = str2.charAt(j - 1);
                if (ch1 == ch2)
                {
                    temp = 0;
                }
                else
                {
                    temp = 1;
                }
                Matrix[i][j] = lowerOfThree(Matrix[i - 1][j] + 1, Matrix[i][j - 1] + 1, Matrix[i - 1][j - 1] + temp);
            }
        }

        return Matrix[n][m];

    }

    public static BigDecimal levenshteinDistancePercent(String str1, String str2)
    {
        int minLenth = str1.length() > str2.length() ? str2.length() : str1.length();
        int val = compareDistance(str1, str2);
        return BigDecimal.ONE.subtract(new BigDecimal(val).divide(new BigDecimal(minLenth), 6, RoundingMode.HALF_UP));
    }

    public static BigDecimal getMatchScore(String sourceName, String targetName) {

        BigDecimal scorce = BigDecimal.ZERO;

        if(StringUtils.isEmpty(sourceName) || StringUtils.isEmpty(targetName)){
            return scorce;
        }

        String[] sourceList = sourceName.toLowerCase().split("[^a-z]");
        String[] targetList = targetName.toLowerCase().split("[^a-z]");


        for (String source : sourceList) {

            if(StringUtils.isEmpty(source) || source.length() < 3){
                continue;
            }

            for (String target : targetList) {
                if(StringUtils.isEmpty(target) || target.length() < 3){
                    continue;
                }
                BigDecimal tempScorce = levenshteinDistancePercent(source, target);
                if(tempScorce.compareTo(scorce) >= 0){
                    scorce = tempScorce;
                }

            }
        }
        return scorce;
    }


    /**
     *  取所有单词匹配平均分
     * @param sourceName
     * @param targetName
     * @return
     */
    public static BigDecimal getAverageScore(String sourceName, String targetName, int parseInt) {

        BigDecimal scorce = BigDecimal.ZERO;

        if(StringUtils.isEmpty(sourceName) || StringUtils.isEmpty(targetName)){
            return scorce;
        }

        String[] sourceList1 = sourceName.toLowerCase().split("[^a-z0-9]");
        String[] targetList1 = targetName.toLowerCase().split("[^a-z0-9]");
        String[] sourceList = Arrays.stream(sourceList1).filter(s -> !"".equals(s)).toArray(String[]::new);
        String[] targetList = Arrays.stream(targetList1).filter(s -> !"".equals(s)).toArray(String[]::new);

        String[] sourceList2 = Arrays.stream(sourceList).filter(s -> !s.chars().allMatch(Character::isDigit))
                .toArray(String[]::new);
        String[] targetList2 = Arrays.stream(targetList).filter(s -> !s.chars().allMatch(Character::isDigit))
                .toArray(String[]::new);
        if(sourceList2.length < parseInt || targetList2.length < parseInt){
            return scorce;
        }
        List<BigDecimal> scorceList = new ArrayList();
        for (String source : sourceList2) {
            if(StringUtils.isEmpty(source) ){
                continue;
            }
            for (String target : targetList2) {
                if(StringUtils.isEmpty(target) ){
                    continue;
                }
                BigDecimal tempScorce = levenshteinDistancePercent(source, target);
                if(tempScorce.compareTo(BigDecimal.ZERO) <= 0){
                   continue;
                }
//                System.out.println(source+"=="+target+"=="+tempScorce);
                scorceList.add(tempScorce);
            }
        }
        if(scorceList.isEmpty()){
            return scorce;
        }
        BigDecimal totalScorce = BigDecimal.ZERO;
        for (BigDecimal ss: scorceList) {
            totalScorce = totalScorce.add(ss);
        }
        scorce = totalScorce.divide(new BigDecimal(targetList2.length), 2, RoundingMode.HALF_UP);
        return scorce;
    }

    public static BigDecimal getMatchScore(List<String> sourceList, List<String> targetList) {

        BigDecimal scorce = BigDecimal.ZERO;

        for (String source : sourceList) {

            if(StringUtils.isEmpty(source) || source.length() < 4){
                continue;
            }
            for (String target : targetList) {
                if(StringUtils.isEmpty(target) || target.length() < 4){
                    continue;
                }
                BigDecimal tempScorce = levenshteinDistancePercent(source, target);
                if(tempScorce.compareTo(scorce) >= 0){
                    scorce = tempScorce;
                }
            }
        }
        return scorce;
    }

    public static void main(String[] args) {
        BigDecimal score = getAverageScore("84 AINA STREET M/NO 98/S25/1544",
                "84 AINA STREET M/NO 98/S25/1544", 3);
        System.out.println(score);
        String  sourceName = "84 AINA STREET M/NO 98/S25/1544 SS55GG";
        String  targetName = "84 AINA STREET M/NO 98/S25/1544 AA6";
        String[] sourceList1 = sourceName.toLowerCase().split("[^a-z0-9]");
        String[] targetList1 = targetName.toLowerCase().split("[^a-z0-9]");
        String[] sourceList = Arrays.stream(sourceList1).filter(s -> !"".equals(s)).toArray(String[]::new);
        String[] targetList = Arrays.stream(targetList1).filter(s -> !"".equals(s)).toArray(String[]::new);

        String[] sourceList2 = Arrays.stream(sourceList).filter(s -> !s.chars().allMatch(Character::isDigit))
                .toArray(String[]::new);
        String[] targetList2 = Arrays.stream(targetList).filter(s -> !s.chars().allMatch(Character::isDigit))
                .toArray(String[]::new);

        System.out.println(Arrays.toString(sourceList2));
        System.out.println(Arrays.toString(targetList2));
    }
}
